package com.star.file;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Iterator;

/**
 * Paths类功能演示
 *
 * Paths类是Java NIO.2 API中的工具类，主要用于创建Path对象：
 * 1. 通过路径字符串创建Path对象
 * 2. 通过URI创建Path对象
 * 3. 提供标准化、解析路径等操作
 *
 * Path接口提供了丰富的路径操作方法，而Paths类是创建Path对象的入口。
 *
 * Paths类与Path接口的关系：
 * 1. Paths是工具类，提供静态方法创建Path对象
 * 2. Path是接口，定义了路径操作的方法
 * 3. Paths.get()是创建Path对象的主要方式
 *
 * Path接口的主要优势：
 * 1. 跨平台兼容性：自动处理不同操作系统的路径分隔符
 * 2. 丰富的操作方法：提供解析、相对化、标准化等操作
 * 3. 不可变性：Path对象是不可变的，线程安全
 * 4. 强类型检查：编译时检查路径操作的正确性
 * 5. 与Files类无缝集成：可以与Files类的静态方法配合使用
 *
 * 常用方法分类：
 * 1. 创建操作：Paths.get(), resolve(), resolveSibling()
 * 2. 查询操作：getFileName(), getParent(), getRoot(), getNameCount(), getName()
 * 3. 比较操作：startsWith(), endsWith(), equals()
 * 4. 转换操作：toString(), toAbsolutePath(), toUri()
 * 5. 处理操作：normalize(), relativize()
 */
public class PathsTest {

    public static void main(String[] args) {
        PathsTest test = new PathsTest();

        try {
            // 演示各种Paths类的功能
            test.demonstratePathsOperations();
        } catch (Exception e) {
            System.err.println("路径操作出错: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 演示Paths类的各种操作
     */
    public void demonstratePathsOperations() throws URISyntaxException, IOException {
        System.out.println("=== Paths类功能演示 ===\n");

        // 1. 创建Path对象
        demonstratePathCreation();

        // 2. Path对象的基本操作
        demonstratePathOperations();

        // 3. 路径解析和相对化
        demonstratePathResolution();

        // 4. 路径比较和匹配
        demonstratePathComparison();
    }

    /**
     * 演示创建Path对象的方法
     */
    private void demonstratePathCreation() throws URISyntaxException {
        System.out.println("1. 创建Path对象演示:");

        // 方法1: 使用Paths.get(String first, String... more)
        Path path1 = Paths.get("/Users/star", "Documents", "file.txt");
        System.out.println("  使用字符串创建路径: " + path1);

        // 方法2: 使用Paths.get(URI uri)
        URI uri = new URI("file:///Users/star/Documents/file.txt");
        Path path2 = Paths.get(uri);
        System.out.println("  使用URI创建路径: " + path2);

        // 方法3: 创建相对路径
        Path relativePath = Paths.get("src", "main", "java", "com", "star", "App.java");
        System.out.println("  创建相对路径: " + relativePath);

        // 方法4: 创建当前目录的路径
        Path currentPath = Paths.get("");
        System.out.println("  当前目录路径: " + currentPath.toAbsolutePath());

        System.out.println();
    }

    /**
     * 演示Path对象的基本操作
     */
    private void demonstratePathOperations() {
        System.out.println("2. Path对象基本操作演示:");

        // 创建一个示例路径
        Path path = Paths.get("/Users/star", "Documents", "projects", "java-basic", "src", "main", "java", "com", "star", "App.java");

        // 基本属性获取
        System.out.println("  完整路径: " + path);
        System.out.println("  文件名: " + path.getFileName());
        System.out.println("  父目录: " + path.getParent());
        System.out.println("  根目录: " + path.getRoot());
        System.out.println("  路径元素数量: " + path.getNameCount());

        // 访问路径中的特定元素
        System.out.println("  第0个元素: " + path.getName(0));
        System.out.println("  第1个元素: " + path.getName(1));
        System.out.println("  第2个元素: " + path.getName(2));

        // 遍历路径中的所有元素
        System.out.print("  所有路径元素: ");
        for (int i = 0; i < path.getNameCount(); i++) {
            System.out.print(path.getName(i) + " ");
        }
        System.out.println();

        // 使用迭代器遍历
        System.out.print("  使用迭代器遍历: ");
        Iterator<Path> iterator = path.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println();

        System.out.println();
    }

    /**
     * 演示路径解析和相对化操作
     */
    private void demonstratePathResolution() {
        System.out.println("3. 路径解析和相对化演示:");

        // 创建基础路径
        Path basePath = Paths.get("/Users/star", "Documents", "projects");

        // 解析子路径
        Path resolvedPath = basePath.resolve("java-basic");
        System.out.println("  基础路径: " + basePath);
        System.out.println("  解析子路径: " + resolvedPath);

        // 解析另一个子路径
        Path resolvedPath2 = basePath.resolve("web-app").resolve("src").resolve("main");
        System.out.println("  多级解析路径: " + resolvedPath2);

        // 解析兄弟路径
        Path siblingPath = basePath.resolveSibling("Downloads");
        System.out.println("  兄弟路径: " + siblingPath);

        // 相对化路径
        Path path1 = Paths.get("/Users/star/Documents/projects/java-basic");
        Path path2 = Paths.get("/Users/star/Documents/projects/web-app");
        Path relativizedPath = path1.relativize(path2);
        System.out.println("  相对化路径 (" + path1.getFileName() + " -> " + path2.getFileName() + "): " + relativizedPath);

        // 标准化路径（移除.和..）
        Path unnormalizedPath = Paths.get("/Users/star/Documents/../Documents/projects/./java-basic");
        Path normalizedPath = unnormalizedPath.normalize();
        System.out.println("  未标准化路径: " + unnormalizedPath);
        System.out.println("  标准化路径: " + normalizedPath);

        System.out.println();
    }

    /**
     * 演示路径比较和匹配操作
     */
    private void demonstratePathComparison() {
        System.out.println("4. 路径比较和匹配演示:");

        Path path1 = Paths.get("/Users/star/Documents/file.txt");
        Path path2 = Paths.get("/Users/star/Documents/file.txt");
        Path path3 = Paths.get("/Users/star/Downloads/file.txt");

        // 路径相等性比较
        System.out.println("  path1.equals(path2): " + path1.equals(path2));
        System.out.println("  path1.equals(path3): " + path1.equals(path3));

        // 起点检查
        Path base = Paths.get("/Users/star");
        System.out.println("  " + path1 + " 是否以 " + base + " 开头: " + path1.startsWith(base));
        System.out.println("  " + path3 + " 是否以 " + base + " 开头: " + path3.startsWith(base));

        // 终点检查
        Path fileName = Paths.get("file.txt");
        System.out.println("  " + path1 + " 是否以 " + fileName + " 结尾: " + path1.endsWith(fileName));
        System.out.println("  " + path3 + " 是否以 " + fileName + " 结尾: " + path3.endsWith(fileName));

        // 转换为字符串
        System.out.println("  路径转字符串: " + path1.toString());

        // 转换为绝对路径
        Path relativePath = Paths.get("src/main/java/com/star/App.java");
        System.out.println("  相对路径: " + relativePath);
        System.out.println("  绝对路径: " + relativePath.toAbsolutePath());

        System.out.println();
    }
}
